/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15Fxx 系列 读取程序区ID号并用软件模拟串口输出显示举例--------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-755-82905966 -------------------------------------------*/
/* --- Tel: 86-755-82948412 -------------------------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使使用了宏晶科技的资料及程序 */
/* 如果要在文章中应用此代码,请在文章中注明使使用了宏晶科技的资料及程序 */
/*---------------------------------------------------------------------*/

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//假定测试芯片的工作频率为18.432MHz

#include "reg51.h"

//-----------------------------------------
//define baudrate const
//BAUD = 256 - FOSC/3/BAUDRATE/M (1T:M=1; 12T:M=12)
//NOTE: (FOSC/3/BAUDRATE) must be greater then 98, (RECOMMEND GREATER THEN 110)

//#define BAUD	0xF400                  // 1200bps @ 11.0592MHz
//#define BAUD	0xFA00                  // 2400bps @ 11.0592MHz
//#define BAUD	0xFD00                  // 4800bps @ 11.0592MHz
//#define BAUD	0xFE80                  // 9600bps @ 11.0592MHz
//#define BAUD	0xFF40                  //19200bps @ 11.0592MHz
//#define BAUD	0xFFA0					//38400bps @ 11.0592MHz

//#define BAUD	0xEC00                  // 1200bps @ 18.432MHz
//#define BAUD	0xF600                  // 2400bps @ 18.432MHz
//#define BAUD	0xFB00                  // 4800bps @ 18.432MHz
//#define BAUD	0xFD80                  // 9600bps @ 18.432MHz
//#define BAUD	0xFEC0                  //19200bps @ 18.432MHz
//#define BAUD	0xFF60                  //38400bps @ 18.432MHz

//#define BAUD	0xE800                  // 1200bps @ 22.1184MHz
//#define BAUD	0xF400                  // 2400bps @ 22.1184MHz
//#define BAUD	0xFA00                  // 4800bps @ 22.1184MHz
//#define BAUD	0xFD00                  // 9600bps @ 22.1184MHz
//#define BAUD	0xFE80                  //19200bps @ 22.1184MHz
#define BAUD	0xFF40                  //38400bps @ 22.1184MHz
//#define BAUD	0xFF80                  //57600bps @ 22.1184MHz

//@ 11.0592MHz
/*
#define D1 80
#define D2 800
#define D3 140
#define D4 200
#define D5 40
#define D6 50
#define D7 1000
*/
//@ 22.1184MHz

#define D1 160
#define D2 1600
#define D3 280
#define D4 400
#define D5 80
#define D6 100
#define D7 2000


#define ID_ADDR_RAM 0x71                //STC104W系列ID号的存放在RAM区的地址
#define ID_ADDR_ROM 0x0ff9              //STC104W系列ID号的存放在ROM区的地址

sfr AUXR = 0x8E;
sbit RXB = P3^0;                        //define UART TX/RX port
sbit TXB = P3^1;

sbit DQ =P3^5;
sbit LED =P3^4;

//定时器2
sfr IE2       = 0xaf;               //中断使能寄存器2
sfr T2H       = 0xD6;               //定时器2高8位
sfr T2L       = 0xD7;               //定时器2低8位
#define T1MS (65536-FOSC/1000)      //1T模式

typedef bit BOOL;
typedef unsigned char BYTE;
typedef unsigned int WORD;

BYTE TBUF,RBUF;
BYTE TDAT,RDAT;
BYTE TCNT,RCNT;
BYTE TBIT,RBIT;
BOOL TING,RING;
BOOL TEND,REND;

void UART_INIT();
void UART_SEND(BYTE dat);

BYTE t, r;
BYTE buf[16];
BYTE pwm=0;
BYTE pwmValue=35;
BYTE full=0;
#define tempMax 70
#define pwmMax 70
#define changeRate1 2
#define changeRate2 3

void delay_stc_us(unsigned int i)
 {
 while(i--);
 }

void delay_stc_ms(unsigned int i)
 {
 while(i--){
 delay_stc_us(10000);
 };
 } 
 void delay_stc_s(unsigned int i)
 {
 while(i--){
 delay_stc_ms(10000);
 };
 } 
 

/***********ds18b20子程序*************************/

/***********ds18b20延迟子函数（晶振11.0592MHz ）*******/

void delay_18B20(unsigned int i)
 {
 while(i--);
 }

/**********ds18b20初始化函数**********************/

void Init_DS18B20(void) 
 {
 unsigned char x=0;
 DQ = 1;          //DQ复位
delay_18B20(D1); //稍做延时
DQ = 0;          //单片机将DQ拉低
delay_18B20(D2); //精确延时 大于 480us
 DQ = 1;          //拉高总线
delay_18B20(D3);
 x=DQ;   
 delay_18B20(D4);
 }

/***********ds18b20读一个字节**************/ 

unsigned char ReadOneChar(void)
 {
 unsigned char i=0;
 unsigned char dat = 0;
 for (i=8;i>0;i--)
 {
     DQ = 0; // 给脉冲信号
    dat>>=1;
     DQ = 1; // 给脉冲信号
    if(DQ)
     dat|=0x80;
     delay_18B20(D5);     //40
 }
    return(dat);
 }

/*************ds18b20写一个字节****************/ 

void WriteOneChar(unsigned char dat)
 {
    unsigned char i=0;
    for (i=8; i>0; i--)
    {
    DQ = 0;
     DQ = dat&0x01;
     delay_18B20(D6); //50
     DQ = 1;
     dat>>=1;
 }
 }

/**************读取ds18b20当前温度************/

unsigned char ReadTemp(void)
 {
	 
 float wendu=0.0;	 
 unsigned char a=0;
 unsigned char b=0;
 unsigned int temp_value=0;
 unsigned char wenduc=0;

Init_DS18B20();
 WriteOneChar(0xCC);     

WriteOneChar(0x44);  

delay_18B20(D7);      

Init_DS18B20();
 WriteOneChar(0xCC);  
 WriteOneChar(0xBE);  

delay_18B20(D7);

a=ReadOneChar();    //读取温度值低位
b=ReadOneChar();      //读取温度值高位

temp_value = b<<8;
 temp_value |= a; 
 
 wendu=temp_value*0.0625;     //得到真实十进制温度值，因为DS18B20
                       //可以精确到0.0625度，所以读回数据的最低位代表的是0.0625度
 wenduc=wendu;					   
 return wenduc;
         
 }


void main()
{
//    BYTE idata *iptr;
    BYTE code *cptr;
    BYTE i;
	int temp=0;
	int temp1=0;
	
	BYTE change=0;
	BYTE changeRate=changeRate1;
	BYTE changeState=0;
	BYTE lowNum=0;
	
	BYTE reSet=0;
	
	LED=1;
	delay_stc_ms(1000);
    
	//定时器1
    TMOD = 0x00;                        //timer0 in 16-bit auto reload mode
    AUXR = 0x80;                        //timer0 working at 1T mode
    TL0 = BAUD;
    TH0 = BAUD>>8;                      //initial timer0 and set reload value
    TR0 = 1;                            //tiemr0 start running
    ET0 = 1;                            //enable timer0 interrupt
    PT0 = 1;                            //improve timer0 interrupt priority
    //EA = 1;                             //open global interrupt switch

	//定时器2
	AUXR |= 0x04;                   //定时器2为1T模式
    T2L = 0xff;                     //初始化计时值
    T2H = 0xf0;
    AUXR |= 0x10;                   //定时器2开始计时
    
    IE2 |= 0x04;                    //开定时器2中断
    EA = 1;

    UART_INIT();
//    iptr = ID_ADDR_RAM;               //从RAM区读取ID号
//    for (i=0; i<7; i++)               //读7个字节
//    {
//        UART_SEND(*iptr++);           //发送ID到串口
//    }
/*    
    cptr = ID_ADDR_ROM;                 //从程序区读取ID号
    for (i=0; i<7; i++)                 //读7个字节
    {
        UART_SEND(*cptr++);             //发送ID到串口
    }
*/

pwmValue=47;
delay_stc_ms(5000);
temp=ReadTemp();

if(temp>0){
	if(temp<tempMax){
		if(temp>45){
			//当高温时，自动调高参数
			pwmValue=pwmMax-(pwmMax-temp)*1.5;
		}else{
			//当高温时，自动调低参数
			pwmValue=pwmMax-(pwmMax-temp)*2;
		}
	}else{
		LED=1;
		change=1;
		full=1;
	}
}else{
	pwmValue=10;
}

    while  (1){
		
		if(reSet==1){
			reSet=0;
			delay_stc_ms(5000);
			temp=ReadTemp();
			if(temp>45){
				//当高温时，自动调高参数
				pwmValue=pwmMax-(pwmMax-temp)*1.5;
			}else{
				//当高温时，自动调低参数
				pwmValue=pwmMax-(pwmMax-temp)*2;
			}
		}
		
		temp=ReadTemp();	
		UART_SEND(0xf1);
		UART_SEND(0xf1);
		UART_SEND(temp/10);
		UART_SEND(temp%10);
		
		/*
		if(temp<=30){
			pwmValue=3*pwmMax/10;
		}else if(temp>30&&temp<=40){
			pwmValue=4*pwmMax/10;
		}else if(temp>40&&temp<=50){
			pwmValue=5*pwmMax/10;
		}else if(temp>50&&temp<=60){
			pwmValue=6*pwmMax/10;
		}else if(temp>60&&temp<=70){
			pwmValue=7*pwmMax/10;
		}else if(temp>70&&temp<=80){
			pwmValue=8*pwmMax/10;
		}else if(temp>80){
			pwmValue=pwmMax;
			LED=1;
		}	*/
		
		//pwmValue=pwmMax*3/4;
		//pwmValue=pwmMax-5;
		
		if(temp1==0){
			temp1=temp;
		}
		

		
		//长时间低温，改变基准参数，进入低速模式
		if(temp<=40){
			lowNum=lowNum+1;
			if(lowNum>=200){
				pwmValue=30;
				lowNum=200;
			}
		}else{
			lowNum=0;
		}

		
		if(temp>tempMax){
			LED=1;
			change=1;
			full=1;
			reSet=1;
			/*
			pwmValue=pwmValue+5;
			//当运行环境变得长期高温时，调节基准参数,进入高温模式
			if(pwmValue>60){
				pwmValue=60;
			}*/
		}else if((temp-temp1)>=1){
			full=0;
			pwmValue=pwmValue+changeRate*(temp-temp1);			
			change=1;
			if(pwmValue>=(pwmMax-5)){
				pwmValue=pwmMax-5;
			}
			if(pwmValue<0){
				pwmValue=0;
			}
		}else if((temp-temp1)<=-1){
			full=0;
			pwmValue=pwmValue+changeRate*(temp-temp1);
			change=1;
			if(pwmValue>=(pwmMax-5)){
				pwmValue=pwmMax-5;
			}
			if(pwmValue<=0){
				pwmValue=0;
			}
		}else{
			full=0;
			change=0;
		}
		
		if(change==1){
			if(changeState==0){
				changeState=1;
				changeRate=changeRate1;
			}else if(changeState==1){
				changeState=1;
				changeRate=changeRate2;
			}
		}else{
			changeState=0;
			changeRate=changeRate1;
		}
		
		

		
		
		UART_SEND(0xf2);
		UART_SEND(0xf2);
		UART_SEND(pwmValue/10);
		UART_SEND(pwmValue%10);
		/*
		UART_SEND(0xf3);
		UART_SEND(0xf3);
		UART_SEND(pwm/10);
		*/
		delay_stc_ms(2000);
		
		temp1=temp;
	};
}

//-----------------------------------------
//Timer interrupt routine for UART

void tm0() interrupt 1 
{
		
    if (RING)
    {
        if (--RCNT == 0)
        {
            RCNT = 3;                   //reset send baudrate counter
            if (--RBIT == 0)
            {
                RBUF = RDAT;            //save the data to RBUF
                RING = 0;               //stop receive
                REND = 1;               //set receive completed flag
            }
            else
            {
                RDAT >>= 1;
                if (RXB) RDAT |= 0x80;	//shift RX data to RX buffer
            }
        }
    }
    else if (!RXB)
    {
        RING = 1;                       //set start receive flag
        RCNT = 4;                       //initial receive baudrate counter
        RBIT = 9;                       //initial receive bit number (8 data bits + 1 stop bit)
    }

    if (--TCNT == 0)
    {
        TCNT = 3;                       //reset send baudrate counter
        if (TING)                       //judge whether sending
        {
            if (TBIT == 0)
            {
                TXB = 0;                //send start bit
                TDAT = TBUF;            //load data from TBUF to TDAT
                TBIT = 9;               //initial send bit number (8 data bits + 1 stop bit)
            }
            else
            {
                TDAT >>= 1;             //shift data to CY
                if (--TBIT == 0)
                {
                    TXB = 1;
                    TING = 0;           //stop send
                    TEND = 1;           //set send completed flag
                }
                else
                {
                    TXB = CY;           //write CY to TX port
                }
            }
        }
    }
}

//-----------------------------------------
//initial UART module variable

void UART_INIT()
{
    TING = 0;
    RING = 0;
    TEND = 1;
    REND = 0;
    TCNT = 0;
    RCNT = 0;
}

//-----------------------------------------
//Send UART data

void UART_SEND(BYTE dat)
{
    while (!TEND);
    TEND = 0;
    TBUF = dat;
    TING = 1;
}
//-----------------------------------------------
//中断服务程序
void t2int() interrupt 12           //中断入口
{

    if(full==1){
		return;
	}

    pwm++;
	if(pwm>pwmMax){
		pwm=0;
	}
	
	if(pwm<=pwmValue){
		LED=1;
	}else{
		LED=0;
	}	 
}
